package com.superme.gateway.exception;

import com.alibaba.fastjson2.JSON;
import com.superme.gateway.bean.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Slf4j
@Component
public class GlobalExceptionHandler implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange).onErrorResume(t -> {
            if (t instanceof LoginException) {
                // 处理自定义异常
                return handleError(exchange, (LoginException) t);
            } else {
                // 处理其他类型的异常
                return handleUnexpectedError(exchange, t);
            }
        });
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }

    private Mono<Void> handleError(ServerWebExchange exchange, LoginException ex) {
        // 构造错误响应
        Result<Object> error = Result.error(ex.getCode(), ex.getMsg());
        log.info("===================== {}", error);
        // 设置响应状态码和 Content-Type
        exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON); // 默认是 UTF-8

        // 序列化为 UTF-8 字节
        byte[] bytes = JSON.toJSONBytes(error);

        // 写入响应体
        return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(bytes)));
    }

    private Mono<Void> handleUnexpectedError(ServerWebExchange exchange, Throwable ex) {
        // 对于未预料到的异常，也可以构造一个通用的错误响应
        Result<Object> error = Result.error(-1, ex.getMessage());
        return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(JSON.toJSONBytes(error))));
    }
}